import java.util.*;

public class Generador {
  private static final Random RANDOM = new Random(0);

  final static String[] tareas = new String[] {"Mezclar cosas peligrosas", "Vender productos", "Comprar suministros", "Hacer café", "Controlar que ande todo bien"};
  final static String[] areas = new String[] {"Laboratorio", "Personal", "Deposito", "Pruebas", "Sueldos", "Compras", "Ventas"};
  final static String[] nombres  = new String[]{"Juan", "José", "Carlos", "Roberto", "Diego", "Armando", "Esteban", "Federico", "Francisco", "Agustín"};
  final static String[] apellidos= new String[]{"Perez", "Rodriguez", "Lopez", "Maradona", "Gutierrez", "Roslan", "Lebrón", "Gimenez"};
  final static String[] eventos = new String[]{"Se lastimó alguien", "Se prendió fuego", "Se acabó el papel higenico", "Hubo una fuga radioactiva", "Explotó todo"};
  final static String[] resultadosAuditorias = new String[] {"Toda la auditoría fue correcta", "El empleado no cumplió con el contrato", "El empleado es genial y habría que ascenderlo"};
  
  public static void main(String args[]){
    int size;
    try {
      size = Integer.parseInt(args[0]);
    } catch (RuntimeException e){
      size = 20;
    }
    makeDeletes();
    int niveles = makeNiveles();
    int areas = size;
    int empleados = 5 * size;
    makeAreas(niveles, areas);
    makeEventos(areas, 5 * size);
    makeEmpleados(niveles, areas, empleados, size);
    makeAccesos(empleados, areas, 20 * size);
  }

  static void makeAccesos(int empleados, int areas, int count){
    int horasDelta = 8;
    long iniT = System.currentTimeMillis() - (horasDelta - 1) * 60L * 60L * 1000L;
    for(int i=0;i<count;i++) {
      int id = i + 1;
      int empleado_id = RANDOM.nextInt(empleados) + 1;
      int area_id = RANDOM.nextInt(areas) + 1;
      String metodo = RANDOM.nextBoolean()?"HUELLA":"CONTRASEÑA";
      int aut = RANDOM.nextInt(2);
      long ingT = iniT - (count - i) * 10L * 60L * 1000L;
      
      String ingreso = new Date(ingT).toString();
      String egreso = (aut == 0)?"null":"'" + new Date(ingT + 60L * 60L * 1000L * (RANDOM.nextInt(horasDelta) + 1)) + "'";
      
      System.out.println(
        "INSERT INTO acceso (acceso_id, empleado_id, area_id, metodo_autenticacion, fue_autorizado, fecha_hora_ingreso, fecha_hora_egreso) "+
         " VALUES (" + id  + ", " + empleado_id + ", " + area_id + ", '" + metodo + "', " + aut + ", '" + ingreso + "', " + egreso + ");"
      );
    } 
  }
  
  static void makeEmpleados(int niveles, int areas, int count, int size){
    List<Integer> area = new ArrayList<Integer>();
    for(int i=0;i<count;i++)area.add((i<areas)?(i+1):null);
    Collections.shuffle(area, RANDOM);
    for(int i=0;i<count;i++) {
      int id = i + 1;
      String nombre = nombres[RANDOM.nextInt(nombres.length)];
      String apellido = apellidos[RANDOM.nextInt(apellidos.length)];
      int categoria;
      if(area.get(i)!=null){
        categoria = 1;
      } else {
        categoria  = RANDOM.nextBoolean()?0:2;
      }
      System.out.println("INSERT INTO empleado (empleado_id, nombre, apellido, categoria) VALUES (" + id  + ", '" + nombre + "', '" + apellido + "', "+categoria+");");
      if(categoria == 0){ //empleado no profesional
        int nivel_id = RANDOM.nextInt(niveles) + 1;
        System.out.println("INSERT INTO empleado_no_profesional (empleado_id, nivel_seguridad_id) VALUES (" + id  + ", " + nivel_id + ");");
        List<Integer> areasNivel = nivelAreas.get(nivel_id);
        if(areasNivel == null) areasNivel = new ArrayList<Integer>();
        if(!areasNivel.isEmpty()){
          areasNivel = new ArrayList<Integer>(areasNivel);
          Collections.shuffle(areasNivel, RANDOM);
          areasNivel = areasNivel.subList(0, RANDOM.nextInt(areasNivel.size()) + 1);
          for(Integer area_id : areasNivel){
            String fInicio = ""+ RANDOM.nextInt(12)+":00";
            String fFin = ""+ (12 + RANDOM.nextInt(12))+":00";
            System.out.println("INSERT INTO empleado_no_profesional_acceso (empleado_id, area_id, franja_horaria_inicio, franja_horaria_fin) VALUES (" + id  + ", " + area_id + ", '" + fInicio + "', '" + fFin +"');");
          }
        }
      }else if(categoria == 1){ //empleado jerarquico
        String fecha = new Date(System.currentTimeMillis() - RANDOM.nextInt(1000) * 24L * 60L * 60L * 1000L).toString();
        int area_id = area.get(i);
        System.out.println("INSERT INTO empleado_jerarquico (empleado_id, area_id, fecha_inicio_responsable) VALUES (" + id  + ", " + area_id + ", '"+fecha+"');");
      }else if(categoria == 2){ //empleado profesional
        int tipo = RANDOM.nextInt(2);
        System.out.println("INSERT INTO empleado_profesional (empleado_id, tipo_profesional) VALUES (" + id  + ", " + tipo + ");");
        if(tipo==0){ //planta permanente
          int area_id = RANDOM.nextInt(areas) + 1;
          System.out.println("INSERT INTO empleado_profesional_planta_permanente (empleado_id, area_id) VALUES (" + id  + ", " + area_id + ");");
        } else if(tipo==1){ //contratado
          System.out.println("INSERT INTO empleado_profesional_contratado (empleado_id) VALUES (" + id  + ");");
          int contratos = RANDOM.nextInt(size) + 1;
          for(int c = 0; c < contratos; c++){
            int area_id = RANDOM.nextInt(areas) + 1;
            long fechaDesde = System.currentTimeMillis() - (RANDOM.nextInt(200) + 200) * 24L * 60L * 60L * 1000L;
            long fechaHasta = fechaDesde + (RANDOM.nextInt(365) + 365) * 24L * 60L * 60L * 1000L;
            String tarea = tareas[RANDOM.nextInt(tareas.length)];
            System.out.println("INSERT INTO contrato (empleado_id, numero_contrato, area_id, fecha_inicio, fecha_fin, tarea) " +
              "VALUES (" + id  + ", " + c + ", " + area_id + ", '" + new Date(fechaDesde) + "', '" + new Date(fechaHasta) + "', '" + tarea + "');");
            int auditorias = RANDOM.nextInt(size) + 1;
            for(int a = 0; a < auditorias; a++){
              long delta = Math.min(System.currentTimeMillis(), fechaHasta) - fechaDesde;
              long fechaAud = fechaDesde + RANDOM.nextLong() % delta;
              String resAud = resultadosAuditorias[RANDOM.nextInt(resultadosAuditorias.length)];
              System.out.println("INSERT INTO auditoria (empleado_id, numero_contrato, auditoria_id, fecha_hora, resultado) " +
                "VALUES (" + id  + ", " + c + ", " + a + ", '" + new Date(fechaAud) + "', '" + resAud + "');");
            }
          }
          
        }
      }
    } 
  }

  static void makeEventos(int areas, int count){
    for(int i=0;i<count;i++) {
      int id = i + 1;
      int area_id = RANDOM.nextInt(areas) + 1;
      String fecha = new Date(System.currentTimeMillis() - RANDOM.nextInt(1000) * 24L * 60L * 60L * 1000L).toString();
      String desc= eventos[RANDOM.nextInt(eventos.length)];
      System.out.println(
        "INSERT INTO evento (evento_id, area_id, fecha_hora, descripcion) VALUES (" + id  + ", " + area_id + ", '" + fecha + "', '"+desc+"');"
      );
    }
  }
  
  final static Map<Integer, List<Integer>> nivelAreas = new HashMap<Integer, List<Integer>>();
  static void makeAreas(int niveles, int count) {
    for(int i=0;i<count;i++) {
      int nivel_id = RANDOM.nextInt(niveles) + 1;
      int id = i+1;
      String nombre = areas[RANDOM.nextInt(areas.length)] + " " + (i+1);
      List<Integer> areasNivel = nivelAreas.get(nivel_id);
      if(areasNivel == null) nivelAreas.put(nivel_id, areasNivel = new ArrayList<Integer>());
      areasNivel.add(id);
      System.out.println("INSERT INTO area (area_id, nivel_seguridad_id, nombre) VALUES (" + id + ", " + nivel_id + ", '"+nombre+"');");
    }
  }

  static int makeNiveles(){
    System.out.println("INSERT INTO nivel_seguridad (nivel_seguridad_id, descripcion) VALUES (1, 'Bajo');");
    System.out.println("INSERT INTO nivel_seguridad (nivel_seguridad_id, descripcion) VALUES (2, 'Medio');");
    System.out.println("INSERT INTO nivel_seguridad (nivel_seguridad_id, descripcion) VALUES (3, 'Alto');");
    return 3;
  }
  
  static void makeDeletes(){
    String[] tables = new String[]{
    "auditoria", "contrato",
    "empleado_profesional_planta_permanente",
    "empleado_profesional_contratado", "empleado_profesional", 
    "empleado_no_profesional_acceso", "empleado_no_profesional",
    "empleado_jerarquico", "acceso", "empleado", "evento", "area", "nivel_seguridad"
    };
    for(String table:tables) {
      System.out.println("DELETE FROM "+table+";");
    }
  }

}
